/**
 * UseWebsocket 类
 */
export class UseWebsocket {
    /**
     * socket地址
     * @private
     */
    private uri: string | undefined
    // 类实例
    private static useWebSocket: UseWebsocket | undefined

    // websocket 实例
    private socket: WebSocket | undefined
    private lockReconnect = true
    private interval: any
    private longStartInterval = 30000

    private timeout: any
    private longStartTimeout = 5000
    //用于消息传递
    private socketMsgMap: Map<string, Function> = new Map<string, Function>()

    public constructor(uri: string) {
        this.uri = uri
    }

    public send(body: any) {
        this.getSocketReadyState() === 1 && this.socket!.send(JSON.stringify(body))
    }

    // 监听该链接返回消息
    public on(key: string, fun: (event: any) => void) {
        if (this.socketMsgMap.has(key)) return
        this.socketMsgMap.set(key, fun)
    }

    public removeOn(key: string) {
        this.socketMsgMap.delete(key)
    }

    public dispose() {
        this.lockReconnect = false
        this.socket && this.socket.close()
        this.timeout && clearInterval(this.timeout)
        this.interval && clearTimeout(this.interval)
    }

    public connectionSocket() {
        if (!this.socket && this.uri) {
            this.socket = new WebSocket(this.uri)
            // 建立监听事件
            this.createListener()
        }
    }

    /**
     * 0正在连接
     * 1连接成功
     * 2连接正在关闭
     * 3已经关闭
     */
    public getSocketReadyState() {
        if (this.socket) {
            return this.socket.readyState
        }
        return 3
    }

    public getSocketMsgFun(key: string) {
        const fun = key ? this.socketMsgMap.get(key) : this.socketMsgMap
        return fun
    }

    private createListener() {
        if (!this.socket) return
        this.socket.addEventListener('open', () => {
            // console.log('socket连接成功', this.socket)
            this.longStart()
        })
        this.socket.addEventListener('message', (event: any) => {
            this.longStart()
            let data = event.data
            try {
                data = JSON.parse(event.data)
            } catch (e) {
                // console.log('收到数据不是JSON', data)
                data = event
                // return
            }

            for (const [key, value] of this.socketMsgMap) {
                value && typeof value === 'function' && value(data)
            }
        })
        this.socket.addEventListener('error', (event: any) => {
            console.error(`Error from server: ${event}`)
        })

        this.socket.addEventListener('close', () => {
            this.socket = undefined
            if (this.lockReconnect) {
                this.uri && this.connectionSocket()
            }
        })
    }

    private longStart() {
        this.interval && clearInterval(this.interval)
        this.timeout && clearTimeout(this.timeout)
        this.interval = setInterval(() => {
            // this.send({
            //     data: 'ping'
            // })

            this.timeout = setTimeout(() => {
                this.lockReconnect = true
                this.socket && this.socket.close()
            }, this.longStartTimeout)
        }, this.longStartInterval)
    }
}
